const EventEmitter = require('events')
const axios = require('axios')
const fs = require('fs-extra')
const path = require('path')
const ffmpeg = require('fluent-ffmpeg')
const ffmpegStatic = require('ffmpeg-static')
const { URL } = require('url')

class M3U8Downloader extends EventEmitter {
  constructor(downloadPath) {
    super()
    this.tasks = new Map()
    this.downloadPath = downloadPath || path.join(require('os').homedir(), 'Downloads', 'm3u8-downloader')
    this.initialized = false
    this.tasksFile = path.join(this.downloadPath, 'tasks.json')
    
    // 设置 FFmpeg 路径
    if (ffmpegStatic) {
      ffmpeg.setFfmpegPath(ffmpegStatic)
      console.log('FFmpeg path set to:', ffmpegStatic)
    } else {
      console.warn('FFmpeg static not found, using system FFmpeg')
    }
  }

  async ensureDownloadPath() {
    try {
      await fs.ensureDir(this.downloadPath)
      this.initialized = true
      console.log('Download path ensured:', this.downloadPath)
      
      // 加载保存的任务
      await this.loadTasks()
    } catch (error) {
      console.error('Failed to create download directory:', error)
      throw error
    }
  }

  // 保存任务到文件
  async saveTasks() {
    try {
      const tasksArray = Array.from(this.tasks.values())
      await fs.writeJson(this.tasksFile, tasksArray, { spaces: 2 })
      console.log(`Saved ${tasksArray.length} tasks to file`)
    } catch (error) {
      console.error('Failed to save tasks:', error)
    }
  }

  // 从文件加载任务
  async loadTasks() {
    try {
      if (await fs.pathExists(this.tasksFile)) {
        const tasksArray = await fs.readJson(this.tasksFile)
        this.tasks.clear()
        
        for (const task of tasksArray) {
          // 过滤掉已完成和已停止的任务，只保留可以恢复的任务
          if (['downloading', 'paused', 'parsing', 'merging'].includes(task.status)) {
            // 重新打开程序时，将暂停的任务状态改为pending，允许重新开始
            if (task.status === 'paused') {
              task.status = 'pending'
              console.log(`Converted paused task to pending: ${task.id}`)
            }
            
            this.tasks.set(task.id, task)
            console.log(`Loaded task: ${task.id} (${task.status})`)
          } else {
            console.log(`Skipped completed/stopped task: ${task.id} (${task.status})`)
          }
        }
        
        console.log(`Loaded ${this.tasks.size} active tasks from file`)
      } else {
        console.log('No tasks file found, starting with empty task list')
      }
    } catch (error) {
      console.error('Failed to load tasks:', error)
    }
  }

  async startDownload(config) {
    console.log('Starting download with config:', config)
    
    // 检查初始化状态
    if (!this.initialized) {
      throw new Error('Downloader not initialized. Please wait for initialization to complete.')
    }
    
    const {
      url,
      outputPath = this.downloadPath,
      filename,
      concurrentThreads = 8,
      retryCount = 3,
      sizeCalculationMethod = 'auto' // 'auto', 'duration', 'sampling', 'estimate'
    } = config

    const taskId = this.generateTaskId()
    console.log('Generated task ID:', taskId)
    
    const task = {
      id: taskId,
      url,
      outputPath,
      filename: filename || this.generateFilename(url),
      concurrentThreads,
      retryCount,
      status: 'parsing',
      progress: 0,
      downloadedSize: 0,
      totalSize: 0,
      segments: [],
      downloadedSegments: 0,
      totalSegments: 0,
      startTime: Date.now(),
      error: null,
      outputFile: null,
      mergeProgress: 0,
      // 添加更多初始状态
      failedSegments: [],
      key: null,
      baseUrl: null
    }


    this.tasks.set(taskId, task)
    await this.saveTasks()
    this.emit('progress', { taskId, ...task })

    // 立即返回 taskId，然后在后台异步处理下载
    this.processDownloadInBackground(taskId, url, outputPath, concurrentThreads, retryCount, sizeCalculationMethod)
    
    console.log('Download started in background, returning taskId immediately')
    return { taskId }
  }

  // 后台异步处理下载
  async processDownloadInBackground(taskId, url, outputPath, concurrentThreads, retryCount, sizeCalculationMethod) {
    try {
      console.log('Background download started for task:', taskId)
      
      const task = this.tasks.get(taskId)
      if (!task) {
        console.error('Task not found:', taskId)
        return
      }

      console.log('Parsing M3U8 file from:', url)
      // 解析M3U8文件
      const m3u8Data = await this.parseM3U8(url)
      console.log('M3U8 parsed successfully, segments:', m3u8Data.segments.length)
      
      // 计算总文件大小
      const totalSize = await this.calculateTotalSize(m3u8Data.segments, sizeCalculationMethod)
      task.totalSize = totalSize
      task.segments = m3u8Data.segments
      task.totalSegments = m3u8Data.segments.length
      task.key = m3u8Data.key
      task.baseUrl = m3u8Data.baseUrl
      task.status = 'downloading'
      
      // 确保进度信息正确初始化
      task.progress = 0
      task.downloadedSize = 0
      task.downloadedSegments = 0
      
      console.log('Total file size calculated:', this.formatFileSize(totalSize))
      console.log('Total segments:', task.totalSegments)
      console.log('Task initialized for download:', {
        id: task.id,
        totalSize: this.formatFileSize(totalSize),
        totalSegments: task.totalSegments,
        status: task.status
      })
      
      this.emit('progress', { taskId, ...task })

      // 创建任务目录
      const taskDir = path.join(outputPath, taskId)
      console.log('Creating task directory:', taskDir)
      await fs.ensureDir(taskDir)

      // 开始下载分片
      console.log('Starting segment download...')
      await this.downloadSegments(taskId, taskDir)

      // 检查下载结果
      if (task.failedSegments && task.failedSegments.length > 0) {
        console.warn(`Download completed with ${task.failedSegments.length} failed segments`)
        const successRate = (task.downloadedSegments / task.totalSegments) * 100
        console.log(`Success rate: ${successRate.toFixed(1)}%`)
        
        // 如果成功率太低，可以选择停止
        if (successRate < 80) {
          throw new Error(`Download failed: Success rate too low (${successRate.toFixed(1)}%)`)
        }
      }

      // 合并分片
      console.log('Starting segment merge...')
      task.status = 'merging'
      this.emit('progress', { taskId, ...task })

      const outputFile = await this.mergeSegments(taskId, taskDir, m3u8Data)
      console.log('Merge completed, output file:', outputFile)

      // 验证输出文件
      if (!await fs.pathExists(outputFile)) {
        throw new Error('Output file was not created')
      }
      
      const outputStats = await fs.stat(outputFile)
      console.log('Output file size:', this.formatFileSize(outputStats.size))

      // 清理临时文件
      console.log('Cleaning up temp files...')
      await this.cleanupTempFiles(taskDir)

             task.status = 'completed'
       task.outputFile = outputFile
       task.progress = 100
       task.completedTime = Date.now()
       await this.saveTasks()
       this.emit('completed', { taskId, ...task })

      console.log('Background download completed successfully')

    } catch (error) {
      console.error('Background download failed:', error)
      const task = this.tasks.get(taskId)
      if (task) {
               task.status = 'error'
       task.error = error.message
       task.errorTime = Date.now()
       await this.saveTasks()
       this.emit('error', { taskId, ...task })
      }
    }
  }

  // 计算总文件大小 - 使用更高效的方法
  async calculateTotalSize(segments, method = 'auto') {
    console.log(`Calculating total size for ${segments.length} segments using method: ${method}`)
    
    // 根据指定方法或自动选择最佳方法
    switch (method) {
      case 'duration':
        try {
          const durationSize = await this.estimateSizeFromDuration(segments)
          if (durationSize > 0) {
            console.log(`Estimated size from duration: ${this.formatFileSize(durationSize)}`)
            return durationSize
          }
        } catch (error) {
          console.warn('Failed to estimate size from duration:', error.message)
        }
        break
        
      case 'sampling':
        try {
          const samplingSize = await this.estimateSizeFromSmartSampling(segments)
          if (samplingSize > 0) {
            console.log(`Estimated size from smart sampling: ${this.formatFileSize(samplingSize)}`)
            return samplingSize
          }
        } catch (error) {
          console.warn('Failed to estimate size from smart sampling:', error.message)
        }
        break
        
      case 'estimate':
        const estimateSize = this.estimateSizeFromSegmentCount(segments)
        console.log(`Estimated size from segment count: ${this.formatFileSize(estimateSize)}`)
        return estimateSize
        
      case 'auto':
      default:
        // 自动选择最佳方法：优先使用时长估算，然后智能采样，最后基于分片数量估算
        try {
          const autoDurationSize = await this.estimateSizeFromDuration(segments)
          if (autoDurationSize > 0) {
            console.log(`Auto-selected duration method: ${this.formatFileSize(autoDurationSize)}`)
            return autoDurationSize
          }
        } catch (error) {
          console.warn('Duration method failed, trying smart sampling:', error.message)
        }
        
        try {
          const autoSamplingSize = await this.estimateSizeFromSmartSampling(segments)
          if (autoSamplingSize > 0) {
            console.log(`Auto-selected smart sampling method: ${this.formatFileSize(autoSamplingSize)}`)
            return autoSamplingSize
          }
        } catch (error) {
          console.warn('Smart sampling failed, using estimate method:', error.message)
        }
        
        const autoEstimateSize = this.estimateSizeFromSegmentCount(segments)
        console.log(`Auto-selected estimate method: ${this.formatFileSize(autoEstimateSize)}`)
        return autoEstimateSize
    }
    
    // 如果所有方法都失败，使用最保守的估算
    const fallbackSize = this.estimateSizeFromSegmentCount(segments)
    console.log(`Using fallback estimate: ${this.formatFileSize(fallbackSize)}`)
    return fallbackSize
  }

  // 策略1: 从时长估算文件大小
  async estimateSizeFromDuration(segments) {
    if (!segments || segments.length === 0) return 0
    
    // 计算总时长
    let totalDuration = 0
    segments.forEach(segment => {
      if (segment.duration) {
        totalDuration += segment.duration
      }
    })
    
    if (totalDuration === 0) return 0
    
    // 基于常见的视频比特率估算文件大小
    // 假设平均比特率为 2Mbps (这是一个相对保守的估计)
    const estimatedBitrate = 2 * 1024 * 1024 // 2 Mbps in bits per second
    const estimatedSize = (totalDuration * estimatedBitrate) / 8 // 转换为字节
    
    // 更新所有分片的大小信息
    const sizePerSegment = Math.round(estimatedSize / segments.length)
    segments.forEach(segment => {
      segment.size = sizePerSegment
    })
    
    return Math.round(estimatedSize)
  }

  // 策略2: 智能采样 - 选择不同位置的分片进行采样
  async estimateSizeFromSmartSampling(segments) {
    if (!segments || segments.length === 0) return 0
    
    const sampleSize = Math.min(5, Math.max(2, Math.floor(segments.length / 20))) // 动态调整样本数量
    const samples = []
    
    // 智能选择采样点：开头、中间、结尾
    if (segments.length >= 3) {
      samples.push(0) // 第一个
      samples.push(Math.floor(segments.length / 2)) // 中间
      samples.push(segments.length - 1) // 最后一个
    } else {
      // 如果分片数量少，全部采样
      for (let i = 0; i < segments.length; i++) {
        samples.push(i)
      }
    }
    
    // 添加一些随机采样点
    const remainingSamples = sampleSize - samples.length
    if (remainingSamples > 0) {
      const usedIndices = new Set(samples)
      let attempts = 0
      while (samples.length < sampleSize && attempts < segments.length) {
        const randomIndex = Math.floor(Math.random() * segments.length)
        if (!usedIndices.has(randomIndex)) {
          samples.push(randomIndex)
          usedIndices.add(randomIndex)
        }
        attempts++
      }
    }
    
    console.log(`Smart sampling ${samples.length} segments from ${segments.length} total`)
    
    let totalSize = 0
    let successCount = 0
    
    // 并发请求采样分片的大小
    const promises = samples.map(async (index) => {
      const segment = segments[index]
      try {
        const response = await axios.head(segment.url, {
          timeout: 10000,
          headers: {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
          }
        })
        
        const contentLength = response.headers['content-length']
        if (contentLength) {
          const size = parseInt(contentLength)
          if (size > 0) {
            segments[index].size = size
            return size
          }
        }
        return null
      } catch (error) {
        console.warn(`Failed to get size for sample segment ${index}:`, error.message)
        return null
      }
    })
    
    const results = await Promise.all(promises)
    results.forEach(size => {
      if (size !== null) {
        totalSize += size
        successCount++
      }
    })
    
    if (successCount > 0) {
      const averageSize = totalSize / successCount
      const estimatedTotalSize = Math.round(averageSize * segments.length)
      
      // 更新所有分片的大小信息
      segments.forEach((segment, index) => {
        if (!segment.size) {
          segment.size = Math.round(averageSize)
        }
      })
      
      return estimatedTotalSize
    }
    
    return 0
  }

  // 策略3: 基于分片数量的动态估算
  estimateSizeFromSegmentCount(segments) {
    if (!segments || segments.length === 0) return 0
    
    // 根据分片数量动态调整每个分片的估算大小
    let estimatedSizePerSegment
    
    if (segments.length <= 10) {
      // 少量分片，可能是高质量视频
      estimatedSizePerSegment = 2 * 1024 * 1024 // 2MB per segment
    } else if (segments.length <= 50) {
      // 中等数量分片
      estimatedSizePerSegment = 1.5 * 1024 * 1024 // 1.5MB per segment
    } else if (segments.length <= 200) {
      // 大量分片，可能是标准质量
      estimatedSizePerSegment = 1024 * 1024 // 1MB per segment
    } else {
      // 超大量分片，可能是低质量或长视频
      estimatedSizePerSegment = 0.8 * 1024 * 1024 // 800KB per segment
    }
    
    const estimatedTotalSize = Math.round(estimatedSizePerSegment * segments.length)
    
    // 更新所有分片的大小信息
    segments.forEach(segment => {
      segment.size = Math.round(estimatedSizePerSegment)
    })
    
    return estimatedTotalSize
  }

  // 格式化文件大小
  formatFileSize(bytes) {
    if (bytes === 0) return '0 B'
    const k = 1024
    const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
    const i = Math.floor(Math.log(bytes) / Math.log(k))
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
  }

  // 计算进度百分比（整数）
  calculateProgress(downloadedSize, totalSize) {
    if (totalSize === 0) return 0
    return Math.round((downloadedSize / totalSize) * 100)
  }

  async parseM3U8(url) {
    try {
      const response = await axios.get(url)
      const content = response.data

      if (!content.includes('#EXTM3U')) {
        throw new Error('Invalid M3U8 file format')
      }

      const lines = content.split('\n')
      const segments = []
      let key = null
      let baseUrl = this.getBaseUrl(url)

      for (let i = 0; i < lines.length; i++) {
        const line = lines[i].trim()
        
        if (line.startsWith('#EXT-X-KEY')) {
          const keyMatch = line.match(/URI="([^"]+)"/)
          if (keyMatch) {
            key = this.resolveUrl(baseUrl, keyMatch[1])
          }
        } else if (line.startsWith('#EXTINF')) {
          const duration = parseFloat(line.match(/#EXTINF:([\d.]+)/)?.[1] || 0)
          const segmentUrl = lines[i + 1]?.trim()
          
          if (segmentUrl && !segmentUrl.startsWith('#')) {
            segments.push({
              url: this.resolveUrl(baseUrl, segmentUrl),
              duration,
              index: segments.length
            })
          }
        }
      }

      return { segments, key, baseUrl }
    } catch (error) {
      throw new Error(`Failed to parse M3U8: ${error.message}`)
    }
  }

  async downloadSegments(taskId, taskDir) {
    const task = this.tasks.get(taskId)
    if (!task || !task.segments) {
      throw new Error('Task or segments not found')
    }

    console.log(`Starting download for task ${taskId} with ${task.segments.length} segments`)
    
    const segments = task.segments
    const totalSegments = segments.length
    let downloadedCount = 0
    let failedSegments = []
    let totalDownloadedSize = 0
    let lastSpeedUpdate = Date.now()
    let lastDownloadedSize = 0
    
    // 更新任务状态
    task.status = 'downloading'
    task.downloadedSegments = 0
    task.totalSegments = totalSegments
    task.downloadedSize = 0
    task.failedSegments = []
    task.progress = 0
    
    // 确保分片信息完整
    if (task.segments && task.segments.length > 0) {
      task.totalSegments = task.segments.length
      // 如果分片没有大小信息，使用总大小平均分配
      if (task.totalSize > 0 && task.totalSegments > 0) {
        const avgSize = Math.floor(task.totalSize / task.totalSegments)
        task.segments.forEach(segment => {
          if (!segment.size) {
            segment.size = avgSize
          }
        })
      }
    }
    
    await this.saveTasks()
    this.emit('progress', { taskId, ...task })

    // 检查暂停状态的函数
    const checkPaused = () => {
      const currentTask = this.tasks.get(taskId)
      return currentTask && currentTask.status === 'paused'
    }

    // 并发下载函数
    const downloadSegment = async (segment, index) => {
      const segmentUrl = segment.url
      const segmentPath = path.join(taskDir, `segment_${index}.ts`)
      
      try {
        // 检查文件是否已存在
        if (await fs.pathExists(segmentPath)) {
          const stats = await fs.stat(segmentPath)
          if (stats.size > 0) {
            console.log(`Segment ${index} already exists, skipping`)
            downloadedCount++
            totalDownloadedSize += stats.size
            task.downloadedSegments = downloadedCount
            task.downloadedSize = totalDownloadedSize
            this.emit('progress', { taskId, ...task })
            return
          }
        }

        const response = await axios({
          method: 'GET',
          url: segmentUrl,
          responseType: 'stream',
          timeout: 30000,
          headers: {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
          }
        })

        const writer = fs.createWriteStream(segmentPath)
        let segmentSize = 0

        response.data.on('data', (chunk) => {
          // 检查是否被暂停
          if (checkPaused()) {
            console.log(`Task ${taskId} paused during segment ${index} download, stopping...`)
            response.data.destroy() // 停止下载流
            writer.end() // 关闭写入流
            return
          }
          
          segmentSize += chunk.length
          totalDownloadedSize += chunk.length
          
          // 计算下载速度
          const now = Date.now()
          if (now - lastSpeedUpdate >= 500) { // 每500ms更新一次速度和进度
            const timeDiff = (now - lastSpeedUpdate) / 1000
            const sizeDiff = totalDownloadedSize - lastDownloadedSize
            const speed = sizeDiff / timeDiff
            
            task.downloadedSize = totalDownloadedSize
            task.downloadedSegments = downloadedCount
            
            // 改进的进度计算逻辑
            if (task.totalSize > 0) {
              // 优先使用文件大小计算进度
              task.progress = Math.floor((totalDownloadedSize / task.totalSize) * 100)
            } else if (task.totalSegments > 0) {
              // 如果没有总大小，使用分片数量计算进度
              task.progress = Math.floor((downloadedCount / task.totalSegments) * 100)
            }
            
            // 确保进度在有效范围内
            task.progress = Math.max(0, Math.min(100, task.progress))
            
            // 每10次进度更新保存一次任务状态
            if (downloadedCount % 10 === 0) {
              this.saveTasks().catch(err => console.error('Failed to save tasks:', err))
            }
            
            console.log(`Task ${taskId} progress: ${task.progress}%, downloaded: ${this.formatFileSize(totalDownloadedSize)}/${this.formatFileSize(task.totalSize)}, segments: ${downloadedCount}/${task.totalSegments}`)
            
            // 立即发送进度更新事件
            this.emit('progress', { 
              taskId, 
              ...task, 
              downloadSpeed: speed 
            })
            
            lastSpeedUpdate = now
            lastDownloadedSize = totalDownloadedSize
          }
        })

        await new Promise((resolve, reject) => {
          let isPaused = false
          
          writer.on('finish', () => {
            if (!isPaused) {
              downloadedCount++
              task.downloadedSegments = downloadedCount
              task.downloadedSize = totalDownloadedSize
              
              // 改进的进度计算逻辑
              if (task.totalSize > 0) {
                // 优先使用文件大小计算进度
                task.progress = Math.floor((totalDownloadedSize / task.totalSize) * 100)
              } else if (task.totalSegments > 0) {
                // 如果没有总大小，使用分片数量计算进度
                task.progress = Math.floor((downloadedCount / task.totalSegments) * 100)
              }
              
              // 确保进度在有效范围内
              task.progress = Math.max(0, Math.min(100, task.progress))
              
              console.log(`Segment ${index} completed. Task ${taskId} progress: ${task.progress}%, downloaded: ${this.formatFileSize(totalDownloadedSize)}/${this.formatFileSize(task.totalSize)}, segments: ${downloadedCount}/${task.totalSegments}`)
              
              // 立即发送进度更新事件
              this.emit('progress', { taskId, ...task })
            }
            resolve()
          })
          writer.on('error', reject)
          
          // 监听暂停状态
          const checkPauseInterval = setInterval(() => {
            if (checkPaused()) {
              isPaused = true
              clearInterval(checkPauseInterval)
              response.data.destroy()
              writer.end()
            }
          }, 100)
          
          response.data.pipe(writer)
        })

      } catch (error) {
        console.error(`Failed to download segment ${index}:`, error.message)
        failedSegments.push({ index, url: segmentUrl, error: error.message })
        
        // 更新失败的分片信息
        task.failedSegments = failedSegments
        this.emit('progress', { taskId, ...task })
      }
    }

    // 使用并发控制
    const concurrency = task.concurrentThreads || 8
    const queue = segments.map((segment, index) => ({ segment, index }))
    
    while (queue.length > 0) {
      // 检查是否被暂停
      if (checkPaused()) {
        console.log(`Task ${taskId} is paused, waiting...`)
        // 等待恢复
        while (checkPaused()) {
          await new Promise(resolve => setTimeout(resolve, 1000)) // 每秒检查一次
        }
        console.log(`Task ${taskId} resumed, continuing download...`)
      }
      
      const batch = queue.splice(0, concurrency)
      await Promise.all(batch.map(({ segment, index }) => downloadSegment(segment, index)))
    }

    // 检查下载成功率
    const successRate = downloadedCount / totalSegments
    console.log(`Download completed: ${downloadedCount}/${totalSegments} segments (${(successRate * 100).toFixed(1)}%)`)

    if (successRate < 0.8) {
      throw new Error(`Download success rate too low: ${(successRate * 100).toFixed(1)}%`)
    }

    // 更新最终状态
    task.downloadedSegments = downloadedCount
    task.downloadedSize = totalDownloadedSize
    task.failedSegments = failedSegments
    this.emit('progress', { taskId, ...task })

    return {
      downloadedCount,
      totalSegments,
      failedSegments,
      totalDownloadedSize
    }
  }

  async mergeSegments(taskId, taskDir, m3u8Data) {
    const task = this.tasks.get(taskId)
    const outputFile = path.join(task.outputPath, `${task.filename}.mp4`)
    
    try {
      // 创建concat文件列表
      const concatFilePath = path.join(taskDir, 'concat.txt')
      const concatLines = []
      
      // 按顺序添加所有分片文件
      for (let i = 0; i < task.totalSegments; i++) {
        const segmentPath = path.join(taskDir, `segment_${i}.ts`)
        // 检查文件是否存在
        if (await fs.pathExists(segmentPath)) {
          concatLines.push(`file '${segmentPath.replace(/\\/g, '/')}'`)
        } else {
          console.warn(`Segment file not found: ${segmentPath}`)
        }
      }
      
      // 写入concat文件
      await fs.writeFile(concatFilePath, concatLines.join('\n'))
      console.log(`Created concat file with ${concatLines.length} segments`)
      
      return new Promise((resolve, reject) => {
        const command = ffmpeg()
          .input(concatFilePath)
          .inputOptions(['-f', 'concat', '-safe', '0'])
          .outputOptions(['-c', 'copy'])
          .output(outputFile)

        if (m3u8Data.key) {
          // 如果有加密，需要解密
          // 注意：FFmpeg不支持 -key_file 参数，应该使用其他方式处理加
          // 密
          console.warn('Encrypted content detected, but key_file parameter is not supported by FFmpeg')
          console.warn('Skipping decryption, output may be encrypted')
        }

        command
          .on('progress', (progress) => {
            task.mergeProgress = Math.round(progress.percent || 0)
            this.emit('progress', { taskId, ...task })
          })
          .on('end', () => {
            console.log('FFmpeg merge completed successfully')
            resolve(outputFile)
          })
          .on('error', (error) => {
            console.error('FFmpeg merge error:', error)
            reject(new Error(`FFmpeg merge failed: ${error.message}`))
          })
          .run()
      })
    } catch (error) {
      console.error('Failed to create concat file:', error)
      throw new Error(`Failed to prepare merge: ${error.message}`)
    }
  }

  // 调试方法：检查分片文件
  async debugSegments(taskId) {
    const task = this.tasks.get(taskId)
    if (!task) {
      console.error('Task not found:', taskId)
      return
    }

    const taskDir = path.join(this.downloadPath, taskId)
    console.log('=== Debug Segments ===')
    console.log('Task directory:', taskDir)
    console.log('Total segments:', task.totalSegments)
    console.log('Downloaded segments:', task.downloadedSegments)

    try {
      // 检查目录是否存在
      const dirExists = await fs.pathExists(taskDir)
      console.log('Directory exists:', dirExists)

      if (dirExists) {
        // 列出目录中的所有文件
        const files = await fs.readdir(taskDir)
        console.log('Files in directory:', files)

        // 检查分片文件
        const segmentFiles = files.filter(f => f.startsWith('segment_') && f.endsWith('.ts'))
        console.log('Segment files found:', segmentFiles.length)

        // 检查每个分片文件的大小
        for (const file of segmentFiles) {
          const filePath = path.join(taskDir, file)
          const stats = await fs.stat(filePath)
          console.log(`${file}: ${this.formatFileSize(stats.size)}`)
        }

        // 检查concat文件
        const concatPath = path.join(taskDir, 'concat.txt')
        if (await fs.pathExists(concatPath)) {
          const concatContent = await fs.readFile(concatPath, 'utf8')
          console.log('Concat file content:')
          console.log(concatContent)
        } else {
          console.log('Concat file not found')
        }
      }
    } catch (error) {
      console.error('Debug error:', error)
    }
  }

  // 调试删除功能
  async debugDelete(taskId) {
    console.log('=== Debug Delete ===')
    console.log('Task ID:', taskId)
    
    const task = this.tasks.get(taskId)
    if (task) {
      console.log('Task found in memory:')
      console.log('- Status:', task.status)
      console.log('- Progress:', task.progress)
      console.log('- Downloaded segments:', task.downloadedSegments)
      console.log('- Total segments:', task.totalSegments)
    } else {
      console.log('Task not found in memory')
    }
    
    const taskDir = path.join(this.downloadPath, taskId)
    try {
      const dirExists = await fs.pathExists(taskDir)
      console.log('Task directory exists:', dirExists)
      
      if (dirExists) {
        const files = await fs.readdir(taskDir)
        console.log('Files in task directory:', files)
        
        // 检查文件权限
        try {
          const stats = await fs.stat(taskDir)
          console.log('Directory permissions:', stats.mode)
        } catch (permError) {
          console.log('Permission check failed:', permError.message)
        }
      }
    } catch (error) {
      console.error('Directory check error:', error)
    }
  }

  async cleanupTempFiles(taskDir) {
    try {
      await fs.remove(taskDir)
    } catch (error) {
      console.error('Failed to cleanup temp files:', error)
    }
  }

  async pauseDownload(taskId) {
    const task = this.tasks.get(taskId)
    if (task && task.status === 'downloading') {
      console.log(`Pausing task: ${taskId}`)
      task.status = 'paused'
      await this.saveTasks()
      this.emit('progress', { taskId, ...task })
      return true
    }
    return false
  }

  async resumeDownload(taskId) {
    const task = this.tasks.get(taskId)
    if (task && (task.status === 'paused' || task.status === 'pending')) {
      console.log(`Resuming task: ${taskId} from status: ${task.status}`)
      
      // 如果任务状态是pending，需要重新开始下载
      if (task.status === 'pending') {
        console.log(`Restarting pending task: ${taskId}`)
        // 重置任务状态
        task.status = 'parsing'
        task.progress = 0
        task.downloadedSize = 0
        task.totalSize = 0
        task.segments = []
        task.downloadedSegments = 0
        task.totalSegments = 0
        task.error = null
        task.mergeProgress = 0
        
        await this.saveTasks()
        this.emit('progress', { taskId, ...task })
        
        // 重新开始下载
        this.processDownloadInBackground(task.id, task.url, task.outputPath, task.concurrentThreads, task.retryCount)
        return true
      } else {
        // 如果任务状态是paused，直接恢复下载
        task.status = 'downloading'
        await this.saveTasks()
        this.emit('progress', { taskId, ...task })
        return true
      }
    }
    return false
  }

  // 强制停止任务
  async forceStopTask(taskId) {
    const task = this.tasks.get(taskId)
    if (task) {
      console.log(`Force stopping task: ${taskId}`)
      
      // 强制设置状态为已停止
      task.status = 'stopped'
      task.error = 'Task force stopped'
      
      // 保存状态并发出事件
      await this.saveTasks()
      this.emit('progress', { taskId, ...task })
      
      return true
    }
    return false
  }

  async getDownloadStatus(taskId) {
    return this.tasks.get(taskId) || null
  }

  // 获取所有任务状态 - 按时间倒序排列
  async getAllTasks() {
    const tasksArray = Array.from(this.tasks.values())
    return tasksArray.sort((a, b) => {
      // 按开始时间倒序排列（最新的在前面）
      const timeA = a.startTime || 0
      const timeB = b.startTime || 0
      return timeB - timeA
    })
  }

  // 同步任务状态
  async syncTaskStatus(taskId, status) {
    const task = this.tasks.get(taskId)
    if (task) {
      task.status = status
      await this.saveTasks()
      this.emit('progress', { taskId, ...task })
      return true
    }
    return false
  }

  // 格式转换
  async convertFormat(inputFile, outputFormat, options = {}) {
    try {
      console.log(`Converting ${inputFile} to ${outputFormat}`)
      
      if (!await fs.pathExists(inputFile)) {
        throw new Error('Input file not found')
      }
      
      const inputDir = path.dirname(inputFile)
      const inputName = path.basename(inputFile, path.extname(inputFile))
      const outputFile = path.join(inputDir, `${inputName}_converted.${outputFormat}`)
      
      // 检查输出文件是否已存在
      if (await fs.pathExists(outputFile)) {
        await fs.remove(outputFile)
      }
      
      const quality = options.quality || '23'
      const outputOptions = this.getOutputOptions(outputFormat, quality)
      
      return new Promise((resolve, reject) => {
        let progress = 0
        
        ffmpeg(inputFile)
          .outputOptions(outputOptions)
          .output(outputFile)
          .on('progress', (info) => {
            // 计算转换进度
            if (info.percent) {
              progress = Math.floor(info.percent)
              console.log(`Conversion progress: ${progress}%`)
            }
          })
          .on('end', () => {
            console.log('Format conversion completed')
            resolve({
              inputFile,
              outputFile,
              format: outputFormat,
              quality
            })
          })
          .on('error', (error) => {
            console.error('Format conversion failed:', error)
            reject(new Error(`Format conversion failed: ${error.message}`))
          })
          .run()
      })
    } catch (error) {
      console.error('Convert format error:', error)
      throw error
    }
  }

  // 获取输出选项
  getOutputOptions(outputFormat, options = {}) {
    const outputOptions = []

    switch (outputFormat.toLowerCase()) {
      case 'mp4':
        outputOptions.push('-c:v', 'libx264')
        outputOptions.push('-c:a', 'aac')
        if (options.quality) {
          outputOptions.push('-crf', options.quality.toString())
        }
        break
      
      case 'avi':
        outputOptions.push('-c:v', 'libx264')
        outputOptions.push('-c:a', 'mp3')
        break
      
      case 'mkv':
        outputOptions.push('-c:v', 'libx264')
        outputOptions.push('-c:a', 'aac')
        break
      
      case 'webm':
        outputOptions.push('-c:v', 'libvpx-vp9')
        outputOptions.push('-c:a', 'libopus')
        break
      
      case 'mov':
        outputOptions.push('-c:v', 'libx264')
        outputOptions.push('-c:a', 'aac')
        break
      
      default:
        // 默认使用MP4格式
        outputOptions.push('-c:v', 'libx264')
        outputOptions.push('-c:a', 'aac')
    }

    // 添加通用选项
    if (options.resolution) {
      outputOptions.push('-vf', `scale=${options.resolution}`)
    }

    if (options.bitrate) {
      outputOptions.push('-b:v', `${options.bitrate}k`)
    }

    if (options.fps) {
      outputOptions.push('-r', options.fps.toString())
    }

    return outputOptions
  }

  getBaseUrl(url) {
    const urlObj = new URL(url)
    return `${urlObj.protocol}//${urlObj.host}${path.dirname(urlObj.pathname)}/`
  }

  resolveUrl(baseUrl, relativeUrl) {
    if (relativeUrl.startsWith('http')) {
      return relativeUrl
    }
    return new URL(relativeUrl, baseUrl).href
  }

  generateTaskId() {
    return `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
  }

  generateFilename(url) {
    const urlObj = new URL(url)
    const pathname = urlObj.pathname
    const basename = path.basename(pathname, path.extname(pathname))
    return basename || 'm3u8_download'
  }
}

module.exports = { M3U8Downloader } 